#include "EpilScanner.h"
#include "EpilScannerException.h"
#include "EpilScannerHelper.h"

#define LINK_PROCESSOR( state )			{ m_processors[ESS_##state] = &EpilScanner::ProcessState_##state; }


EpilScanner::EpilScanner()
{
	LINK_PROCESSOR( Normal );
	LINK_PROCESSOR( InSingleQuoteString );
	LINK_PROCESSOR( InDoubleQuoteString );
	LINK_PROCESSOR( InSingleQuoteEscapeSequence );
	LINK_PROCESSOR( InDoubleQuoteEscapeSequence );
	LINK_PROCESSOR( InDecimal );
	LINK_PROCESSOR( InOctal );
	LINK_PROCESSOR( InHexadecimal );
	LINK_PROCESSOR( InDouble );
	LINK_PROCESSOR( InExponent );
	LINK_PROCESSOR( InIdentifier );
	LINK_PROCESSOR( InLineComment );
	LINK_PROCESSOR( InBlockComment );

	LINK_PROCESSOR( EnterDouble );
	LINK_PROCESSOR( EnterScientific );
	LINK_PROCESSOR( EnterExponent );
	LINK_PROCESSOR( OneZeroPassed );
	LINK_PROCESSOR( OneEqualPassed );
	LINK_PROCESSOR( OneUnequalPassed );
	LINK_PROCESSOR( OneLessPassed );
	LINK_PROCESSOR( OneGreaterPassed );
	LINK_PROCESSOR( OneCloseBracketPassed );
	LINK_PROCESSOR( OneMinusPassed );
	LINK_PROCESSOR( HalfBlockCommentPassed );
	LINK_PROCESSOR( OneDotPassed );
	LINK_PROCESSOR( TwoDotPassed );
	LINK_PROCESSOR( OneEscapeDigitPassedInSingle );
	LINK_PROCESSOR( OneEscapeDigitPassedInDouble );
	LINK_PROCESSOR( TwoEscapeDigitPassedInSingle );
	LINK_PROCESSOR( TwoEscapeDigitPassedInDouble );

	m_keywordMap.insert( make_pair( t("do"), ETT_KwDo ) );
	m_keywordMap.insert( make_pair( t("end"), ETT_KwEnd ) );
	m_keywordMap.insert( make_pair( t("while"), ETT_KwWhile ) );
	m_keywordMap.insert( make_pair( t("repeat"), ETT_KwRepeat ) );
	m_keywordMap.insert( make_pair( t("until"), ETT_KwUntil ) );
	m_keywordMap.insert( make_pair( t("if"), ETT_KwIf ) );
	m_keywordMap.insert( make_pair( t("then"), ETT_KwThen ) );
	m_keywordMap.insert( make_pair( t("elseif"), ETT_KwElseif ) );
	m_keywordMap.insert( make_pair( t("else"), ETT_KwElse ) );
	m_keywordMap.insert( make_pair( t("for"), ETT_KwFor ) );
	m_keywordMap.insert( make_pair( t("in"), ETT_KwIn ) );
	m_keywordMap.insert( make_pair( t("function"), ETT_KwFunction ) );
	m_keywordMap.insert( make_pair( t("local"), ETT_KwLocal ) );
	m_keywordMap.insert( make_pair( t("return"), ETT_KwReturn ) );
	m_keywordMap.insert( make_pair( t("break"), ETT_KwBreak ) );
	m_keywordMap.insert( make_pair( t("continue"), ETT_KwContinue ) );
	m_keywordMap.insert( make_pair( t("nil"), ETT_KwNil ) );
	m_keywordMap.insert( make_pair( t("true"), ETT_KwTrue ) );
	m_keywordMap.insert( make_pair( t("false"), ETT_KwFalse ) );
	m_keywordMap.insert( make_pair( t("and"), ETT_KwAnd ) );
	m_keywordMap.insert( make_pair( t("or"), ETT_KwOr ) );
	m_keywordMap.insert( make_pair( t("not"), ETT_KwNot ) );
}


EpilScanner::~EpilScanner()
{
}


void EpilScanner::ScanFile( const tstring & filename )
{
	tifstream program( filename.c_str() );
	this->Scan( program );
}


void EpilScanner::ScanString( const tstring & str )
{
	tstringstream program;
	program << str;
	this->Scan( program );
}


void EpilScanner::Scan( tistream & program )
{
	EpilScanState curState = ESS_Normal;
	m_curString = t("");

	m_stringBeginLine = 1;
	m_stringBeginColumn = 1;
	m_curCharLine = 1;
	m_curCharColumn = 1;

	while( program.good() )
	{
		tchar curChar = t('\0');
		program.read( &curChar, 1 );

		ScanProcessor processor = m_processors[curState];
		curState = (this->*processor)( curChar );

		m_curCharColumn++;
		if( curChar == t('\n') )
		{
			m_curCharLine++;
			m_curCharColumn = 1;
		}
	}

	this->AddToken( EpilToken( ETT_EndOfStream, this->GetCurrentCharLexLocation() ) );
}


void EpilScanner::AddToken( const EpilToken & token )
{
	m_tokens.push_back( token );
}


void EpilScanner::AppendCharToCurrentString( tchar ch )
{
	m_curString += ch;

	if( m_curString.length() == 1 )
	{
		m_stringBeginLine = m_curCharLine;
		m_stringBeginColumn = m_curCharColumn;
	}
}


void EpilScanner::ClearCurrentString()
{
	m_curString.clear();
}


EpilLexLocation EpilScanner::GetCurrentCharLexLocation() const
{
	return EpilLexLocation( m_curCharLine, m_curCharColumn );
}


EpilLexLocation EpilScanner::GetStringBeginLexLocation() const
{
	return EpilLexLocation( m_stringBeginLine, m_stringBeginColumn );
}


void EpilScanner::AddIdentifierOrKeyword()
{
	map<tstring, EpilTokenType>::const_iterator it = m_keywordMap.find( m_curString );
	if( it == m_keywordMap.end() )
	{
		this->AddToken( EpilToken( ETT_Identifier, this->GetStringBeginLexLocation(), m_curString ) );
	}
	else
	{
		this->AddToken( EpilToken( it->second, this->GetStringBeginLexLocation(), m_curString ) );
	}
}


EpilScanner::EpilScanCharType EpilScanner::GetScanCharType( tchar ch )
{
	switch( ch )
	{
	case t('\r'):
	case t('\n'):
		return ESCT_LineEnder;
	case t('\t'):
	case t(' '):
		return ESCT_TabOrSpace;

	case t('('):
		return ESCT_OpenParenthese;
	case t(')'):
		return ESCT_CloseParenthese;
	case t('['):
		return ESCT_OpenBracket;
	case t(']'):
		return ESCT_CloseBracket;
	case t('{'):
		return ESCT_OpenBrace;
	case t('}'):
		return ESCT_CloseBrace;

	case t('+'):
		return ESCT_Add;
	case t('-'):
		return ESCT_Minus;
	case t('*'):
		return ESCT_Star;
	case t('/'):
		return ESCT_Slash;
	case t('\\'):
		return ESCT_Backslash;
	case t('^'):
		return ESCT_Power;
	case t('%'):
		return ESCT_Percent;
	case t('.'):
		return ESCT_Dot;
	case t('<'):
		return ESCT_Less;
	case t('>'):
		return ESCT_Greater;
	case t('='):
		return ESCT_Equal;
	case t('~'):
		return ESCT_Unequal;
	case t('#'):
		return ESCT_Sharp;
	case t(':'):
		return ESCT_Colon;
	case t(';'):
		return ESCT_Semicolon;
	case t('\''):
		return ESCT_SingleQuote;
	case t('\"'):
		return ESCT_DoubleQuote;
	case t(','):
		return ESCT_Comma;
	case t('\0'):
		return ESCT_Null;
	}

	if( tisalpha( ch ) || ch == t('_') )
	{
		return ESCT_AlphaOrUnderscore;
	}

	if( tisdigit( ch ) )
	{
		return ESCT_Digit;
	}

	return ESCT_Other;
}


EpilScanner::EpilScanState EpilScanner::ProcessState_Normal( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->ClearCurrentString();
		if( ch == t('0') )
		{
			return ESS_OneZeroPassed;
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InDecimal;
		}

	case ESCT_SingleQuote:
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneMinusPassed;
	case ESCT_Dot:
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneDotPassed;
	case ESCT_Less:
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneGreaterPassed;
	case ESCT_Equal:
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneEqualPassed;
	case ESCT_Unequal:
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneUnequalPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InSingleQuoteString( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
		throw EpilScannerException( t("Unexpected end of file. Single quoted string expected."), this->GetCurrentCharLexLocation() );
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of line. Single quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_String, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Backslash:
		return ESS_InSingleQuoteEscapeSequence;

	case ESCT_DoubleQuote:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_AlphaOrUnderscore:
	case ESCT_Digit:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
		this->AppendCharToCurrentString( ch );
		return ESS_InSingleQuoteString;

	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InDoubleQuoteString( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
		throw EpilScannerException( t("Unexpected end of file. Double quoted string expected."), this->GetCurrentCharLexLocation() );
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of line. Double quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_String, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Backslash:
		return ESS_InDoubleQuoteEscapeSequence;

	case ESCT_SingleQuote:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_AlphaOrUnderscore:
	case ESCT_Digit:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
		this->AppendCharToCurrentString( ch );
		return ESS_InDoubleQuoteString;

	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InSingleQuoteEscapeSequence( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_AlphaOrUnderscore:
		switch( ch )
		{
		case t('a'):
			this->AppendCharToCurrentString( t('\a') );
			return ESS_InSingleQuoteString;
		case t('b'):
			this->AppendCharToCurrentString( t('\b') );
			return ESS_InSingleQuoteString;
		case t('f'):
			this->AppendCharToCurrentString( t('\f') );
			return ESS_InSingleQuoteString;
		case t('n'):
			this->AppendCharToCurrentString( t('\n') );
			return ESS_InSingleQuoteString;
		case t('r'):
			this->AppendCharToCurrentString( t('\r') );
			return ESS_InSingleQuoteString;
		case t('t'):
			this->AppendCharToCurrentString( t('\t') );
			return ESS_InSingleQuoteString;
		case t('v'):
			this->AppendCharToCurrentString( t('\v') );
			return ESS_InSingleQuoteString;
		default:
			throw EpilScannerException( t("Invalid escape char detected."), this->GetCurrentCharLexLocation() );
		}

	case ESCT_DoubleQuote:
		this->AppendCharToCurrentString( t('\"') );
		return ESS_InSingleQuoteString;

	case ESCT_Backslash:
		this->AppendCharToCurrentString( t('\\') );
		return ESS_InSingleQuoteString;

	case ESCT_Null:
		throw EpilScannerException( t("Unexpected end of file. Escape character in single quoted string expected."), this->GetCurrentCharLexLocation() );
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of line. Escape character in single quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			throw EpilScannerException( t("Octal digit must be less than 8."), this->GetCurrentCharLexLocation() );
		}
		else
		{
			m_curEscapeStr += ch;
		}
		return ESS_OneEscapeDigitPassedInSingle;
		
	case ESCT_SingleQuote:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid escape char detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneEscapeDigitPassedInSingle( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of file. Escape character in single quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			m_curString += ch;
			return ESS_InSingleQuoteString;
		}
		else
		{
			m_curEscapeStr += ch;
		}
		return ESS_TwoEscapeDigitPassedInSingle;

	case ESCT_SingleQuote:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			return ESS_InSingleQuoteString;
		}

	case ESCT_DoubleQuote:
	case ESCT_Backslash:
	case ESCT_AlphaOrUnderscore:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
	default:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			this->AppendCharToCurrentString( ch );
			return ESS_InSingleQuoteString;
		}
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_TwoEscapeDigitPassedInSingle( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of file. Escape character in single quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			m_curString += ch;
			return ESS_InSingleQuoteString;
		}
		else
		{
			m_curEscapeStr += ch;
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			return ESS_InSingleQuoteString;
		}

	case ESCT_SingleQuote:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			return ESS_InSingleQuoteString;
		}

	case ESCT_DoubleQuote:
	case ESCT_Backslash:
	case ESCT_AlphaOrUnderscore:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
	default:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			this->AppendCharToCurrentString( ch );
			return ESS_InSingleQuoteString;
		}
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneEscapeDigitPassedInDouble( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of file. Escape character in double quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			m_curString += ch;
			return ESS_InDoubleQuoteString;
		}
		else
		{
			m_curEscapeStr += ch;
		}
		return ESS_TwoEscapeDigitPassedInDouble;

	case ESCT_DoubleQuote:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			return ESS_InDoubleQuoteString;
		}

	case ESCT_SingleQuote:
	case ESCT_Backslash:
	case ESCT_AlphaOrUnderscore:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
	default:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			this->AppendCharToCurrentString( ch );
			return ESS_InDoubleQuoteString;
		}
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_TwoEscapeDigitPassedInDouble( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of file. Escape character in single quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			m_curString += ch;
			return ESS_InDoubleQuoteString;
		}
		else
		{
			m_curEscapeStr += ch;
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			return ESS_InDoubleQuoteString;
		}

	case ESCT_DoubleQuote:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			return ESS_InDoubleQuoteString;
		}

	case ESCT_SingleQuote:
	case ESCT_Backslash:
	case ESCT_AlphaOrUnderscore:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
	default:
		{
			unsigned char escapeValue = EpilScannerHelper::ScanOctal( m_curEscapeStr );
			m_curEscapeStr.clear();
			m_curString += escapeValue;
			this->AppendCharToCurrentString( ch );
			return ESS_InDoubleQuoteString;
		}
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InDoubleQuoteEscapeSequence( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_AlphaOrUnderscore:
		switch( ch )
		{
		case t('a'):
			this->AppendCharToCurrentString( t('\a') );
			return ESS_InDoubleQuoteString;
		case t('b'):
			this->AppendCharToCurrentString( t('\b') );
			return ESS_InDoubleQuoteString;
		case t('f'):
			this->AppendCharToCurrentString( t('\f') );
			return ESS_InDoubleQuoteString;
		case t('n'):
			this->AppendCharToCurrentString( t('\n') );
			return ESS_InDoubleQuoteString;
		case t('r'):
			this->AppendCharToCurrentString( t('\r') );
			return ESS_InDoubleQuoteString;
		case t('t'):
			this->AppendCharToCurrentString( t('\t') );
			return ESS_InDoubleQuoteString;
		case t('v'):
			this->AppendCharToCurrentString( t('\v') );
			return ESS_InDoubleQuoteString;
		default:
			throw EpilScannerException( t("Invalid escape char detected."), this->GetCurrentCharLexLocation() );
		}

	case ESCT_SingleQuote:
		this->AppendCharToCurrentString( t('\'') );
		return ESS_InDoubleQuoteString;

	case ESCT_Backslash:
		this->AppendCharToCurrentString( t('\\') );
		return ESS_InDoubleQuoteString;

	case ESCT_Null:
		throw EpilScannerException( t("Unexpected end of file. Escape character in single quoted string expected."), this->GetCurrentCharLexLocation() );
	case ESCT_LineEnder:
		throw EpilScannerException( t("Unexpected end of line. Escape character in single quoted string expected."), this->GetCurrentCharLexLocation() );

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			throw EpilScannerException( t("Octal digit must be less than 8."), this->GetCurrentCharLexLocation() );
		}
		else
		{
			m_curEscapeStr += ch;
		}
		return ESS_OneEscapeDigitPassedInDouble;

	case ESCT_DoubleQuote:
	case ESCT_TabOrSpace:
	case ESCT_Semicolon:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Add:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Minus:
	case ESCT_Dot:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Equal:
	case ESCT_Unequal:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid escape char detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InDecimal( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_AlphaOrUnderscore:
		if(	ch == t('_') )
		{
			return ESS_InDecimal;
		}
		else if( ch == t('e') || ch == t('E') )
		{
			return ESS_EnterScientific;
		}
		else
		{
			this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
			this->ClearCurrentString();
			this->AppendCharToCurrentString( ch );
			return ESS_InIdentifier;
		}

	case ESCT_Digit:
		this->AppendCharToCurrentString( ch );
		return ESS_InDecimal;
	case ESCT_Dot:
		this->AppendCharToCurrentString( ch );
		return ESS_EnterDouble;

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneMinusPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneGreaterPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneEqualPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneUnequalPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_EnterDouble( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		if( ch == t('e') || ch == t('E') )
		{
			return ESS_EnterScientific;
		}
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AppendCharToCurrentString( ch );
		return ESS_InDouble;

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Less:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneEqualPassed;
	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InLineComment;

	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_TwoDotPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_EnterScientific( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Digit:
		this->AppendCharToCurrentString( t('e') );
		this->AppendCharToCurrentString( ch );
		return ESS_InExponent;

	case ESCT_Add:
	case ESCT_Minus:
		this->AppendCharToCurrentString( t('e') );
		this->AppendCharToCurrentString( ch );
		return ESS_EnterExponent;

	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
	case ESCT_Semicolon:
	case ESCT_AlphaOrUnderscore:
	case ESCT_SingleQuote:
	case ESCT_DoubleQuote:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Unequal:
	case ESCT_Equal:
	case ESCT_Dot:
	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Exponent part expected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InDouble( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		if( ch == t('e') || ch == t('E') )
		{
			return ESS_EnterScientific;
		}
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AppendCharToCurrentString( ch );
		return ESS_InDouble;

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Less:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneEqualPassed;
	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InLineComment;

	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_Double, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InExponent( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AppendCharToCurrentString( ch );
		return ESS_InExponent;

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Less:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneEqualPassed;
	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InLineComment;

	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_Scientific, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_EnterExponent( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Digit:
		this->AppendCharToCurrentString( ch );
		return ESS_InExponent;

	case ESCT_Add:
	case ESCT_Minus:
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
	case ESCT_Semicolon:
	case ESCT_AlphaOrUnderscore:
	case ESCT_SingleQuote:
	case ESCT_DoubleQuote:
	case ESCT_OpenParenthese:
	case ESCT_CloseParenthese:
	case ESCT_OpenBracket:
	case ESCT_CloseBracket:
	case ESCT_OpenBrace:
	case ESCT_CloseBrace:
	case ESCT_Star:
	case ESCT_Slash:
	case ESCT_Power:
	case ESCT_Percent:
	case ESCT_Sharp:
	case ESCT_Colon:
	case ESCT_Comma:
	case ESCT_Less:
	case ESCT_Greater:
	case ESCT_Unequal:
	case ESCT_Equal:
	case ESCT_Dot:
	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Exponent expected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneZeroPassed( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_AlphaOrUnderscore:
		if(	ch == t('_') )
		{
			return ESS_InOctal;
		}
		else
		{
			if( ch == t('x') || ch == t('X') )
			{
				return ESS_InHexadecimal;
			}
			else
			{
				this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
				this->ClearCurrentString();
				this->AppendCharToCurrentString( ch );
				return ESS_InIdentifier;
			}
		}

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			throw EpilScannerException( t("Octal digit must be less than 8."), this->GetCurrentCharLexLocation() );
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InOctal;
		}
	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneMinusPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneGreaterPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneEqualPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_Decimal, this->GetStringBeginLexLocation(), t("0") ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneUnequalPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InOctal( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_AlphaOrUnderscore:
		if(	ch == t('_') )
		{
			return ESS_InOctal;
		}
		else
		{
			this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
			this->ClearCurrentString();
			this->AppendCharToCurrentString( ch );
			return ESS_InIdentifier;
		}

	case ESCT_Digit:
		if( ch == t('8') || ch == t('9') )
		{
			throw EpilScannerException( t("Octal digit must be less than 8."), this->GetCurrentCharLexLocation() );
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InOctal;
		}
	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneMinusPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneGreaterPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneEqualPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_Octal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneUnequalPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InHexadecimal( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_AlphaOrUnderscore:
		if(	ch == t('_') )
		{
			return ESS_InOctal;
		}
		else
		{
			if( ( ch >= t('a') && ch <= t('f') ) || ( ch >= t('A') && ch <= t('F') ) )
			{
				this->AppendCharToCurrentString( ch );
				return ESS_InHexadecimal;
			}
			else
			{
				this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
				this->ClearCurrentString();
				this->AppendCharToCurrentString( ch );
				return ESS_InIdentifier;
			}
		}

	case ESCT_Digit:
		this->AppendCharToCurrentString( ch );
		return ESS_InHexadecimal;

	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneMinusPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneGreaterPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneEqualPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_Hexadecimal, this->GetStringBeginLexLocation(), m_curString ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneUnequalPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InIdentifier( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Semicolon:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_AlphaOrUnderscore:
	case ESCT_Digit:
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;

	case ESCT_SingleQuote:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Dot:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneDotPassed;
	case ESCT_Minus:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneMinusPassed;
	case ESCT_Less:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneGreaterPassed;
	case ESCT_Equal:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneEqualPassed;
	case ESCT_Unequal:
		this->AddIdentifierOrKeyword();
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_OneUnequalPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InLineComment( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_LineEnder:
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->ClearCurrentString();
		return ESS_HalfBlockCommentPassed;
	default:
		return ESS_InLineComment;
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_InBlockComment( tchar ch )
{
	if( GetScanCharType( ch ) == ESCT_CloseBracket )
	{
		this->ClearCurrentString();
		return ESS_OneCloseBracketPassed;
	}

	return ESS_InBlockComment;
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneEqualPassed( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		if( ch == t('0') )
		{
			return ESS_OneZeroPassed;
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InDecimal;
		}

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneMinusPassed;
	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_OpAssign, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;

	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_OpEqual, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneUnequalPassed( tchar ch )
{
	if( GetScanCharType( ch ) == ESCT_Equal )
	{
		this->AddToken( EpilToken( ETT_OpUnequal, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;
	}

	throw EpilScannerException( tstring( t("Expected '=', not ") ) + ch, this->GetCurrentCharLexLocation() );
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneLessPassed( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		if( ch == t('0') )
		{
			return ESS_OneZeroPassed;
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InDecimal;
		}

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneMinusPassed;
	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_OpLessThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;

	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_OpLessThanOrEqual, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneGreaterPassed( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		if( ch == t('0') )
		{
			return ESS_OneZeroPassed;
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InDecimal;
		}

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneMinusPassed;
	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_OpGreaterThan, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;

	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_OpGreaterThanOrEqual, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneCloseBracketPassed( tchar ch )
{
	if( GetScanCharType( ch ) == ESCT_CloseBracket )
	{
		this->ClearCurrentString();
		return ESS_Normal;
	}

	return ESS_InBlockComment;
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneMinusPassed( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		if( ch == t('0') )
		{
			return ESS_OneZeroPassed;
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InDecimal;
		}

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneDotPassed;
	case ESCT_Less:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_OpMinus, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneEqualPassed;

	case ESCT_Minus:
		this->ClearCurrentString();
		return ESS_InLineComment;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_HalfBlockCommentPassed( tchar ch )
{
	if( GetScanCharType( ch ) == ESCT_OpenBracket )
	{
		this->ClearCurrentString();
		return ESS_InBlockComment;
	}

	this->ClearCurrentString();
	return ESS_InLineComment;
}


EpilScanner::EpilScanState EpilScanner::ProcessState_OneDotPassed( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		if( ch == t('0') )
		{
			return ESS_OneZeroPassed;
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InDecimal;
		}

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Less:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneEqualPassed;
	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_OpTableMemberAccess, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InLineComment;

	case ESCT_Dot:
		this->AppendCharToCurrentString( ch );
		return ESS_TwoDotPassed;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}


EpilScanner::EpilScanState EpilScanner::ProcessState_TwoDotPassed( tchar ch )
{
	EpilScanCharType type = GetScanCharType( ch );

	switch( type )
	{
	case ESCT_Null:
	case ESCT_TabOrSpace:
	case ESCT_LineEnder:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;
	case ESCT_Semicolon:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpSemicolon, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_AlphaOrUnderscore:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AppendCharToCurrentString( ch );
		return ESS_InIdentifier;
	case ESCT_Digit:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		if( ch == t('0') )
		{
			return ESS_OneZeroPassed;
		}
		else
		{
			this->AppendCharToCurrentString( ch );
			return ESS_InDecimal;
		}

	case ESCT_SingleQuote:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InSingleQuoteString;
	case ESCT_DoubleQuote:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InDoubleQuoteString;

	case ESCT_OpenParenthese:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseParenthese:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseParenthese, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBracket:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBracket:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBracket, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_OpenBrace:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpenBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_CloseBrace:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_CloseBrace, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Add:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpAdd, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Star:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMultiply, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Slash:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpDivide, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Power:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpPower, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Percent:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpMod, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Sharp:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpLength, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Colon:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpObjectMemberAccess, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;
	case ESCT_Comma:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		this->AddToken( EpilToken( ETT_OpComma, this->GetCurrentCharLexLocation() ) );
		return ESS_Normal;

	case ESCT_Less:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneLessPassed;
	case ESCT_Greater:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneGreaterPassed;
	case ESCT_Unequal:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneUnequalPassed;
	case ESCT_Equal:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_OneEqualPassed;
	case ESCT_Minus:
		this->AddToken( EpilToken( ETT_OpStringConcatenate, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_InLineComment;

	case ESCT_Dot:
		this->AddToken( EpilToken( ETT_OpVariousParameters, this->GetStringBeginLexLocation() ) );
		this->ClearCurrentString();
		return ESS_Normal;

	case ESCT_Backslash:
	case ESCT_Other:
	default:
		throw EpilScannerException( t("Invalid character detected."), this->GetCurrentCharLexLocation() );
	}
}